#include "PicParams.h"
//#include "../Tool/Macros.h"
#include "rapidjson/error/en.h"
//#include "../IO/IO.h"
//#include "../Parallel/ParallelMPI.h"

#include <cmath>
#include <algorithm>
#include <fstream>
#include <iostream>

using namespace std;

//---------------------------------------------------------------------------------------------------------------------
//PicParams : open & parse the input data file, test that parameters are coherent
//---------------------------------------------------------------------------------------------------------------------
PicParams::PicParams() :
    const_c(299792458.0),
    const_e(1.6021766208e-19),
    const_emass(9.10938356e-31),
    const_ephi0(8.854187817620389e-12),
    const_pi(3.1415926),
    const_boltz(1.3806e-23),
    const_h(6.62606957e-34)
{
    //================== read and parse parameter.inp file of json format ======================
    std::ifstream in(file_name);
    if(!in.is_open())
    {
        log_error<<"fail to read input file: data/parameter.inp";
    }

    std::string json_content((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
    in.close();

    if(dom.Parse(json_content.c_str()).HasParseError())
    {
         log_error<<"params dom error at offset " << dom.GetErrorOffset() << ": " << GetParseError_En(dom.GetParseError());
    }

    //================== read parameters ======================

    if(!get_string(method, "method"))
    {
        method = "explicit";
    }

    if(!get_string(solver_type, "solver_type"))
    {
        solver_type = "petsc";
    }

    if(!get_double_vector(cell_length, "cell_length"))
    {
        log_error<<"no cell_length";
    }

    if(!get_int(nx_source_left, "nx_source_left"))
    {
        nx_source_left = 0;
    }

    if(!get_double_vector(sim_length, "sim_length"))
    {
        log_error<<"no sim_length";
    }

    if(!get_int(petsc_ksp_process_number, "petsc_ksp_process_number"))
    {
        petsc_ksp_process_number = 0;
    }

    if(!get_double(petsc_ksp_tolerance_rtol, "petsc_ksp_tolerance_rtol"))
    {
        petsc_ksp_tolerance_rtol = 1.0e-5;
    }

    if(!get_double(imp_theta, "imp_theta"))
    {

    }

    if(!get_double(imp_iteration_number, "imp_iteration_number"))
    {

    }

    if(!get_bool(is_same_weight, "is_same_weight"))
    {
        is_same_weight = true;
    }

    if(!get_bool(is_self_consistent_electric_field, "is_self_consistent_electric_field"))
    {
        is_self_consistent_electric_field = true;
    }
    log_info<<"is_self_consistent_electric_field: "<<is_self_consistent_electric_field;

    if(!get_bool(is_temperature_anisotropic, "is_temperature_anisotropic"))
    {
        is_temperature_anisotropic = false;
    }
    log_info<<"is_temperature_anisotropic: "<<is_temperature_anisotropic;

    if(!get_string(read_data_file_name, "read_data_file_name"))
    {

    }

    if(!get_double(v_transport, "v_transport"))
    {
        v_transport = 0.0;
    }

    if(!get_double(velocity_transport, "velocity_transport"))
    {
        velocity_transport = 0.0;
    }

    if(!get_string(geometry, "geometry"))
    {
        log_error<<"no geometry";
    }

    if(!get_int(interpolation_order, "interpolation_order"))
    {
        interpolation_order = 1;
    }

    if(!get_int(projection_order, "projection_order"))
    {
        projection_order = 1;
    }

    if(!get_string_vector(bc_em_type_x, "bc_em_type_x"))
    {

    }

    if(!get_string_vector(bc_em_type_y, "bc_em_type_y"))
    {

    }

    if(!get_string_vector(bc_em_type_z, "bc_em_type_z"))
    {

    }

    if(!get_double_vector(bc_em_value_x, "bc_em_value_x"))
    {

    }

    if(!get_double_vector(bc_em_value_y, "bc_em_value_y"))
    {

    }

    if(!get_double_vector(bc_em_value_z, "bc_em_value_z"))
    {

    }

    if(!get_double(dt, "dt"))
    {
        log_error<<"no dt";
    }

    if(!get_int(timestep_simulation, "timestep_simulation"))
    {
        log_error<<"no timestep_simulation";
    }

    if(!get_int(timestep_io, "timestep_io"))
    {
        log_error<<"no timestep_io";
    }

    if(!get_int(timestep_average, "timestep_average"))
    {
        timestep_average = timestep_io;
    }

    if(!get_int(timestep_restore, "timestep_restore"))
    {
        timestep_restore = timestep_io;
    }

    if(!get_int(timestep_collision, "timestep_collision"))
    {
        timestep_coulomb = 1;
    }

    if(!get_int(timestep_coulomb, "timestep_coulomb"))
    {
        timestep_coulomb = 1;
    }

    if(!get_int(timestep_DSMC, "timestep_DSMC"))
    {
        timestep_DSMC = 1;
    }

    if(!get_double(collision_zoom_factor, "collision_zoom_factor"))
    {
        collision_zoom_factor = 1.0;
    }

    if(!get_double_vector(region_collision_zoom, "region_collision_zoom"))
    {

    }

    if(!get_bool(is_continue, "is_continue"))
    {
        is_continue = false;
    }

    if(!get_int_vector(number_of_procs, "number_of_procs"))
    {

    }

    if(!get_double_vector(externB, "externB"))
    {

    }

    if(!get_string(grid_type, "grid_type"))
    {
        grid_type = "simple";
    }

    read_species();

    read_particle_source();

    read_collision();

    read_psi();

    read_diagnostic();

    compute();

}

void PicParams::read_species()
{
    if(dom.HasMember("Species") && dom["Species"].IsArray())
    {
        const rapidjson::Value& arr = dom["Species"];
        species_param.resize(arr.Size());
        for(int i = 0; i < arr.Size(); ++i)
        {
            const rapidjson::Value& tmp = arr[i];

            if(!get_struct_string(tmp, species_param[i].species_name, "species_name"))
            {

            }

            if(!get_struct_string(tmp, species_param[i].species_type, "species_type"))
            {

            }

            if(!get_struct_string(tmp, species_param[i].init_position_type, "init_position_type"))
            {

            }

            if(!get_struct_string(tmp, species_param[i].init_velocity_type, "init_velocity_type"))
            {

            }

            if(!get_struct_double(tmp, species_param[i].c_part_max, "c_part_max"))
            {

            }

            if(!get_struct_double(tmp, species_param[i].mass, "mass"))
            {

            }

            if(!get_struct_double(tmp, species_param[i].charge, "charge"))
            {

            }

            if(!get_struct_double(tmp, species_param[i].number_density, "number_density"))
            {

            }

            if(!get_struct_int(tmp, species_param[i].n_part_per_cell, "n_part_per_cell"))
            {

            }


            if(!get_struct_int(tmp, species_param[i].n_part_per_cell_for_weight, "n_part_per_cell_for_weight"))
            {

            }


            if(!get_struct_double(tmp, species_param[i].temperature, "temperature"))
            {
                species_param[i].temperature = 0.0;
            }

            if(!get_struct_double(tmp, species_param[i].temperature_x, "temperature_x"))
            {
                species_param[i].temperature_x = 0.0;
            }
            //log_info<<"temperature_x: "<<species_param[i].temperature_x;

            if(!get_struct_double(tmp, species_param[i].temperature_y, "temperature_y"))
            {
                species_param[i].temperature_y = 0.0;
            }
            //log_info<<"temperature_y: "<<species_param[i].temperature_y;

            if(!get_struct_double(tmp, species_param[i].temperature_z, "temperature_z"))
            {
                species_param[i].temperature_z = 0.0;
            }
            //log_info<<"temperature_z: "<<species_param[i].temperature_z;

            if(!get_struct_double_vector(tmp, species_param[i].mean_velocity, "mean_velocity"))
            {
                species_param[i].mean_velocity.resize(3, 0.0);
            }

            if(!get_struct_int(tmp, species_param[i].timestep_frozen, "timestep_frozen"))
            {
                species_param[i].timestep_frozen = 1;
            }

            if(!get_struct_string(tmp, species_param[i].bc_part_type_west, "bc_part_type_west"))
            {

            }

            if(!get_struct_string(tmp, species_param[i].bc_part_type_east, "bc_part_type_east"))
            {

            }

            if(!get_struct_string(tmp, species_param[i].bc_part_type_south, "bc_part_type_south"))
            {

            }

            if(!get_struct_string(tmp, species_param[i].bc_part_type_north, "bc_part_type_north"))
            {

            }

            if(!get_struct_string(tmp, species_param[i].bc_part_type_bottom, "bc_part_type_bottom"))
            {

            }

            if(!get_struct_string(tmp, species_param[i].bc_part_type_up, "bc_part_type_up"))
            {

            }


            //=============== parameters for DSMC ===================================

            if(!get_struct_double(tmp, species_param[i].diameter, "diameter"))
            {

            }

            if(!get_struct_double(tmp, species_param[i].ref_temperature, "ref_temperature"))
            {

            }

            if(!get_struct_double(tmp, species_param[i].visc_temp_index, "visc_temp_index"))
            {

            }

            if(!get_struct_double(tmp, species_param[i].vss_scat_inv, "vss_scat_inv"))
            {

            }


            //==============Parameters for physical sputtering and backscattering============
            if(!get_struct_int(tmp, species_param[i].atomic_number, "atomic_number"))
            {

            }

            if(!get_struct_double(tmp, species_param[i].atomic_mass, "atomic_mass"))
            {

            }

            if(!get_struct_double(tmp, species_param[i].surface_binding_energy, "surface_binding_energy"))
            {

            }

            if(!get_struct_double(tmp, species_param[i].density_solid, "density_solid"))
            {

            }

            //============Parameters for backscattering as the target
            if(!get_struct_int(tmp, species_param[i].ne2, "ne2"))
            {

            }

            if(!get_struct_int_vector(tmp, species_param[i].an2_vector, "an2_vector"))
            {

            }

            if(!get_struct_int_vector(tmp, species_param[i].nw2_vector, "nw2_vector"))
            {

            }

            species_param[i].weight = species_param[i].number_density / species_param[i].n_part_per_cell_for_weight;
        }
    }
}


int PicParams::get_species_number(const std::string &species_name)
{
    for(int i = 0; i < species_param.size(); i++)
    {
        if(species_name == species_param[i].species_name)
        {
            return i;
        }
    }
    log_error<<"no species name: "<<species_name;
    return -1;
}


void PicParams::read_particle_source()
{
    if(dom.HasMember("ParticleSource") && dom["ParticleSource"].IsArray())
    {
        const rapidjson::Value& arr = dom["ParticleSource"];
        particle_source_param.resize(arr.Size());
        for(int i = 0; i < arr.Size(); ++i)
        {
            const rapidjson::Value& tmp = arr[i];

            if(!get_struct_string(tmp, particle_source_param[i].species_name, "species_name"))
            {

            }
            else
            {
                particle_source_param[i].species_number = get_species_number(particle_source_param[i].species_name);

            }

            if(!get_struct_string(tmp, particle_source_param[i].species_name_dependent, "species_name_dependent"))
            {

            }
            else
            {
                particle_source_param[i].species_number_dependent = get_species_number(particle_source_param[i].species_name_dependent);

            }


            if(!get_struct_string(tmp, particle_source_param[i].ps_type, "ps_type"))
            {

            }

            if(!get_struct_string(tmp, particle_source_param[i].load_type, "load_type"))
            {

            }

            if(!get_struct_string(tmp, particle_source_param[i].emit_type, "emit_type"))
            {

            }

            if(!get_struct_double(tmp, particle_source_param[i].number_density, "number_density"))
            {

            }

            if(!get_struct_double(tmp, particle_source_param[i].dn, "dn"))
            {

            }

            if(!get_struct_double(tmp, particle_source_param[i].dq, "dq"))
            {

            }

            if(!get_struct_double(tmp, particle_source_param[i].dn_scale_down, "dn_scale_down"))
            {
                particle_source_param[i].dn_scale_down = 10.0;
            }

            if(!get_struct_int(tmp, particle_source_param[i].load_particle_number, "load_particle_number"))
            {

            }

            if(!get_struct_double(tmp, particle_source_param[i].temperature, "temperature"))
            {

            }

            if(!get_struct_double_vector(tmp, particle_source_param[i].mean_velocity, "mean_velocity"))
            {

            }

            if(!get_struct_double_vector(tmp, particle_source_param[i].load_position_start, "load_position_start"))
            {

            }

            if(!get_struct_double_vector(tmp, particle_source_param[i].load_position_end, "load_position_end"))
            {

            }

            if(!get_struct_int(tmp, particle_source_param[i].timestep_update, "timestep_update"))
            {
                particle_source_param[i].timestep_update = 1;
            }

            if(!get_struct_bool(tmp, particle_source_param[i].is_dependent, "is_dependent"))
            {

            }

            if(!get_struct_bool(tmp, particle_source_param[i].is_every_time, "is_every_time"))
            {
                particle_source_param[i].is_every_time = true;
            }

            if(!get_struct_int(tmp, particle_source_param[i].emit_particle_number, "emit_particle_number"))
            {

            }

            if(!get_struct_double(tmp, particle_source_param[i].emit_flux, "emit_flux"))
            {

            }

            if(!get_struct_string(tmp, particle_source_param[i].emit_position, "emit_position"))
            {

            }

            if(!get_struct_double(tmp, particle_source_param[i].emit_offset, "emit_offset"))
            {
                particle_source_param[i].emit_offset = 0.2;
            }

            if(!get_struct_double(tmp, particle_source_param[i].kp, "kp"))
            {
                particle_source_param[i].kp = 1.0;
            }

            if(!get_struct_double(tmp, particle_source_param[i].ki, "ki"))
            {
                particle_source_param[i].ki = 1.0e-2;
            }

            if(!get_struct_double(tmp, particle_source_param[i].kd, "kd"))
            {
                particle_source_param[i].kd = 1.0;
            }
        }
    }
}


void PicParams::read_collision()
{
    if(dom.HasMember("Collision") && dom["Collision"].IsArray())
    {
        const rapidjson::Value& arr = dom["Collision"];
        collision_param.resize(arr.Size());
        for(int i = 0; i < arr.Size(); ++i)
        {
            const rapidjson::Value& tmp = arr[i];

            if(!get_struct_string(tmp, collision_param[i].collision_type, "collision_type"))
            {

            }

            if(!get_struct_string_vector(tmp, collision_param[i].species_name_list, "species_name_list"))
            {

            }
            else
            {
                collision_param[i].species_number_list.resize(collision_param[i].species_name_list.size());
                for(int j = 0; j < collision_param[i].species_name_list.size(); j++)
                {
                    collision_param[i].species_number_list[j] = get_species_number(collision_param[i].species_name_list[j]);
                }
            }

            if(!get_struct_double_vector(tmp, collision_param[i].region_collision_zoom_start, "region_collision_zoom_start"))
            {

            }

            if(!get_struct_double_vector(tmp, collision_param[i].region_collision_zoom_end, "region_collision_zoom_end"))
            {

            }

            if(!get_struct_string(tmp, collision_param[i].cs_file_name, "cs_file_name"))
            {

            }

            if(!get_struct_int(tmp, collision_param[i].timestep_collision, "timestep_collision"))
            {
                collision_param[i].timestep_collision = 1;
            }

            if(!get_struct_double(tmp, collision_param[i].time_zoom_factor, "time_zoom_factor"))
            {
                collision_param[i].time_zoom_factor = 1.0;
            }
        }
    }
}


void PicParams::read_psi()
{
    if(dom.HasMember("PSI") && dom["PSI"].IsArray())
    {
        const rapidjson::Value& arr = dom["PSI"];
        psi_param.resize(arr.Size());
        for(int i = 0; i < arr.Size(); ++i)
        {
            const rapidjson::Value& tmp = arr[i];

            if(!get_struct_string(tmp, psi_param[i].psi_type, "psi_type"))
            {

            }

            if(!get_struct_string_vector(tmp, psi_param[i].species_name_list, "species_name_list"))
            {

            }
            else
            {
                psi_param[i].species_number_list.resize(psi_param[i].species_name_list.size());
                for(int j = 0; j < psi_param[i].species_name_list.size(); j++)
                {
                    psi_param[i].species_number_list[j] = get_species_number(psi_param[i].species_name_list[j]);
                }
            }

            if(!get_struct_double(tmp, psi_param[i].position_offset, "position_offset"))
            {
                psi_param[i].position_offset = 0.1;
            }

            if(!get_struct_bool(tmp, psi_param[i].is_self_consistent, "is_self_consistent"))
            {
                psi_param[i].is_self_consistent = true;
            }

            if(!get_struct_string(tmp, psi_param[i].psi_position, "psi_position"))
            {

            }

            if(!get_struct_double(tmp, psi_param[i].recycling_factor, "recycling_factor"))
            {

            }

            if(!get_struct_double(tmp, psi_param[i].recycling_temperature, "recycling_temperature"))
            {

            }

        }
    }
}


void PicParams::read_diagnostic()
{
    if(dom.HasMember("Diagnostic") && dom["Diagnostic"].IsArray())
    {
        const rapidjson::Value& arr = dom["Diagnostic"];
        diagnostic_param.resize(arr.Size());
        for(int i = 0; i < arr.Size(); ++i)
        {
            const rapidjson::Value& tmp = arr[i];

            if(!get_struct_int(tmp, diagnostic_param[i].vedf_n_velocity, "vedf_n_velocity"))
            {

            }

            if(!get_struct_double_vector(tmp, diagnostic_param[i].edf_max_energy, "edf_max_energy"))
            {

            }


            if(!get_struct_string_vector(tmp, diagnostic_param[i].vedf_species_name_list, "vedf_species_name_list"))
            {

            }
            else
            {
                diagnostic_param[i].vedf_species_number_list.resize(diagnostic_param[i].vedf_species_name_list.size());
                for(int j = 0; j < diagnostic_param[i].vedf_species_name_list.size(); j++)
                {
                    diagnostic_param[i].vedf_species_number_list[j] = get_species_number(diagnostic_param[i].vedf_species_name_list[j]);
                }

                diagnostic_param[i].vedf_n_species = diagnostic_param[i].vedf_species_number_list.size();
            }

            if(!get_struct_double_vector(tmp, diagnostic_param[i].vedf_position, "vedf_position"))
            {

            }
            else
            {
                diagnostic_param[i].vedf_n_position = diagnostic_param[i].vedf_position.size();
            }
        }
    }
}


void PicParams::compute()
{
    cell_length_inv.resize(cell_length.size());
    for(int i = 0; i < cell_length.size(); i++)
    {
        cell_length_inv[i] = 1.0 / cell_length[i];
    }

    if(geometry=="1d3v")
    {
        n_dim_field = 1;
        n_dim_particle = 3;

        if(number_of_procs.size() == 0)
        {
            number_of_procs.resize(1, 0);
        }
    }
    else if(geometry=="2d3v")
    {
        n_dim_field = 2;
        n_dim_particle = 3;

        if(number_of_procs.size() == 0)
        {
            number_of_procs.resize(2, 0);
        }
    }
    else if (geometry=="3d3v")
    {
        n_dim_field = 3;
        n_dim_particle = 3;

        if(number_of_procs.size() == 0)
        {
            number_of_procs.resize(3, 0);
        }
    }
    else
    {
        log_error<<"geometry error: " << geometry;
    }


    dims_field.resize(n_dim_field);
    dims_field_global.resize(n_dim_field);
    dims_space.resize(n_dim_field);
    dims_space_global.resize(n_dim_field);

    oversize.resize(n_dim_field);
    for(int i = 0; i < n_dim_field; i++)
    {
        oversize[i] = interpolation_order;
    }

    local_min.resize(n_dim_field);
    local_max.resize(n_dim_field);
    cell_starting_global_index.resize(n_dim_field);

}


bool PicParams::get_string(std::string& cpp_value, std::string value_name)
{
    if(dom.HasMember(value_name.c_str()) && dom[value_name.c_str()].IsString())
    {
        cpp_value = dom[value_name.c_str()].GetString();
        return true;
    }
    return false;
}

bool PicParams::get_double(double& cpp_value, std::string value_name)
{
    if(dom.HasMember(value_name.c_str()) && dom[value_name.c_str()].IsDouble())
    {
        cpp_value = dom[value_name.c_str()].GetDouble();
        return true;
    }
    return false;
}


bool PicParams::get_int(int& cpp_value, std::string value_name)
{
    if(dom.HasMember(value_name.c_str()) && dom[value_name.c_str()].IsInt())
    {
        cpp_value = dom[value_name.c_str()].GetInt();
        return true;
    }
    return false;
}

bool PicParams::get_bool(bool& cpp_value, std::string value_name)
{
    if(dom.HasMember(value_name.c_str()) && dom[value_name.c_str()].IsBool())
    {
        cpp_value = dom[value_name.c_str()].GetBool();
        return true;
    }
    return false;
}

bool PicParams::get_string_vector(std::vector<std::string>& cpp_value, std::string value_name)
{
    if(dom.HasMember(value_name.c_str()) && dom[value_name.c_str()].IsArray())
    {
        cpp_value.resize(dom[value_name.c_str()].Size());
        for(int i = 0; i < cpp_value.size(); i++)
        {
            const rapidjson::Value& tmp = dom[value_name.c_str()][i];
            if(tmp.IsString())
            {
                cpp_value[i] = tmp.GetString();
            }
            else
            {
                return false;
            }

        }
        return true;
    }
    return false;
}


bool PicParams::get_double_vector(std::vector<double>& cpp_value, std::string value_name)
{
    if(dom.HasMember(value_name.c_str()) && dom[value_name.c_str()].IsArray())
    {
        cpp_value.resize(dom[value_name.c_str()].Size());
        for(int i = 0; i < cpp_value.size(); i++)
        {
            const rapidjson::Value& tmp = dom[value_name.c_str()][i];
            if(tmp.IsDouble())
            {
                cpp_value[i] = tmp.GetDouble();
            }
            else
            {
                return false;
            }

        }
        return true;
    }
    return false;
}


bool PicParams::get_int_vector(std::vector<int>& cpp_value, std::string value_name)
{
    if(dom.HasMember(value_name.c_str()) && dom[value_name.c_str()].IsArray())
    {
        cpp_value.resize(dom[value_name.c_str()].Size());
        for(int i = 0; i < cpp_value.size(); i++)
        {
            const rapidjson::Value& tmp = dom[value_name.c_str()][i];
            if(tmp.IsInt())
            {
                cpp_value[i] = tmp.GetInt();
            }
            else
            {
                return false;
            }

        }
        return true;
    }
    return false;
}


bool PicParams::get_struct_string(const rapidjson::Value& json_value, std::string& cpp_value, std::string value_name)
{
    if(json_value.HasMember(value_name.c_str()) && json_value[value_name.c_str()].IsString())
    {
        cpp_value = json_value[value_name.c_str()].GetString();
        return true;
    }
    return false;
}


bool PicParams::get_struct_double(const rapidjson::Value& json_value, double& cpp_value, std::string value_name)
{
    if(json_value.HasMember(value_name.c_str()) && json_value[value_name.c_str()].IsDouble())
    {
        cpp_value = json_value[value_name.c_str()].GetDouble();
        return true;
    }
    return false;
}


bool PicParams::get_struct_int(const rapidjson::Value& json_value, int& cpp_value, std::string value_name)
{
    if(json_value.HasMember(value_name.c_str()) && json_value[value_name.c_str()].IsInt())
    {
        cpp_value = json_value[value_name.c_str()].GetInt();
        return true;
    }
    return false;
}

bool PicParams::get_struct_bool(const rapidjson::Value& json_value, bool& cpp_value, std::string value_name)
{
    if(json_value.HasMember(value_name.c_str()) && json_value[value_name.c_str()].IsBool())
    {
        cpp_value = json_value[value_name.c_str()].GetBool();
        return true;
    }
    return false;
}

bool PicParams::get_struct_string_vector(const rapidjson::Value& json_value, std::vector<std::string>& cpp_value, std::string value_name)
{
    if(json_value.HasMember(value_name.c_str()) && json_value[value_name.c_str()].IsArray())
    {
        cpp_value.resize(json_value[value_name.c_str()].Size());
        for(int i = 0; i < cpp_value.size(); i++)
        {
            const rapidjson::Value& tmp = json_value[value_name.c_str()][i];
            if(tmp.IsString())
            {
                cpp_value[i] = tmp.GetString();
            }
            else
            {
                return false;
            }

        }
        return true;
    }
    return false;
}


bool PicParams::get_struct_double_vector(const rapidjson::Value& json_value, std::vector<double>& cpp_value, std::string value_name)
{
    if(json_value.HasMember(value_name.c_str()) && json_value[value_name.c_str()].IsArray())
    {
        cpp_value.resize(json_value[value_name.c_str()].Size());
        for(int i = 0; i < cpp_value.size(); i++)
        {
            const rapidjson::Value& tmp = json_value[value_name.c_str()][i];
            if(tmp.IsDouble())
            {
                cpp_value[i] = tmp.GetDouble();
            }
            else
            {
                return false;
            }

        }
        return true;
    }
    return false;
}


bool PicParams::get_struct_int_vector(const rapidjson::Value& json_value, std::vector<int>& cpp_value, std::string value_name)
{
    if(json_value.HasMember(value_name.c_str()) && json_value[value_name.c_str()].IsArray())
    {
        cpp_value.resize(json_value[value_name.c_str()].Size());
        for(int i = 0; i < cpp_value.size(); i++)
        {
            const rapidjson::Value& tmp = json_value[value_name.c_str()][i];
            if(tmp.IsInt())
            {
                cpp_value[i] = tmp.GetInt();
            }
            else
            {
                return false;
            }

        }
        return true;
    }
    return false;
}
